//<script>
(() => {
  'use strict';

  const STORAGE_KEY = 'ufi_bg_video_cfg';
  const ENDPOINT_KEY = 'ufi_upload_endpoint';
  const defaultCfg = {
    enabled: false,
    url: '',
    muted: true,
    loop: true,
    volume: 0,
    playbackRate: 1,
    opacity: 1
  };

  const LIGHT_BG = '#fff7c2';
  const DARK_BG = '#ffd24d';

  const readCfg = () => {
    try { const raw = localStorage.getItem(STORAGE_KEY); return raw ? { ...defaultCfg, ...JSON.parse(raw) } : { ...defaultCfg }; }
    catch { return { ...defaultCfg }; }
  };
  const saveCfg = (c) => localStorage.setItem(STORAGE_KEY, JSON.stringify(c || {}));

  function toast(msg, color) {
    try { window.createToast && window.createToast(String(msg), color || ''); }
    catch { alert(String(msg)); }
  }

  function tryPlay(v) { setTimeout(() => { try { v.play().catch(() => {}); } catch {} }, 60); }

  function applyVideoCfg(v, cfg) {
    v.muted = !!cfg.muted;
    v.loop = !!cfg.loop;
    v.volume = Math.max(0, Math.min(1, Number(cfg.volume || 0)));
    try { v.playbackRate = Math.max(0.25, Math.min(4, Number(cfg.playbackRate || 1))); } catch {}
    v.style.opacity = String(cfg.opacity ?? 1);

    if (cfg.enabled && cfg.url) {
      if (v.src !== cfg.url) v.src = cfg.url;
      tryPlay(v);
    } else {
      try { v.pause(); } catch {}
      v.removeAttribute('src');
      try { v.load(); } catch {}
    }
  }

  function ensureVideoLayer() {
    const cfg = readCfg();
    let v = document.getElementById('ufi-bg-video');
    if (!v) {
      v = document.createElement('video');
      v.id = 'ufi-bg-video';
      v.autoplay = true;
      v.playsInline = true;
      v.setAttribute('playsinline', 'true');
      v.setAttribute('webkit-playsinline', 'true');
      v.style.position = 'fixed';
      v.style.inset = '0';
      v.style.minWidth = '100%';
      v.style.minHeight = '100%';
      v.style.width = '100%';
      v.style.height = '100%';
      v.style.objectFit = 'cover';
      v.style.zIndex = '-1';
      v.style.pointerEvents = 'none';
      v.style.background = 'black';
      document.body.appendChild(v);

      // 回到页面/交互时续播
      document.addEventListener('visibilitychange', () => {
        if (!document.hidden && readCfg().enabled && readCfg().url) tryPlay(v);
      });
      window.addEventListener('pageshow', () => tryPlay(v));
      window.addEventListener('focus', () => tryPlay(v));
      window.addEventListener('click', () => tryPlay(v), { capture: true });
      window.addEventListener('touchstart', () => tryPlay(v), { passive: true });

      // 被重渲染移除则重建
      const obs = new MutationObserver(() => {
        if (!document.getElementById('ufi-bg-video')) {
          try { obs.disconnect(); } catch {}
          ensureVideoLayer();
        }
      });
      obs.observe(document.body, { childList: true, subtree: false });
    }
    applyVideoCfg(v, cfg);
    return v;
  }

  function getActionsBar() {
    return document.querySelector('.actions-buttons') || null;
  }
  function getFunctionsContainer() {
    return document.querySelector('.functions-container') || document.body;
  }

  function pickFile(accept = 'video/*') {
    return new Promise(resolve => {
      const input = document.createElement('input');
      input.type = 'file';
      input.accept = accept;
      input.style.display = 'none';
      document.body.appendChild(input);
      input.onchange = () => {
        const f = input.files && input.files[0];
        document.body.removeChild(input);
        resolve(f || null);
      };
      input.click();
    });
  }

  async function discoverUploadEndpoint() {
    const cached = localStorage.getItem(ENDPOINT_KEY);
    if (cached) return cached;

    const origFetch = window.fetch;
    let found = '';
    window.fetch = async function(url, init) {
      try {
        if (init && init.body instanceof FormData) {
          const hasFile = Array.from(init.body.entries()).some(([k, v]) => k === 'file' && v && (v.name || v.type));
          if (hasFile) found = String(url);
        }
      } catch {}
      return origFetch.apply(this, arguments);
    };

    try {
      const tiny = new File([new Uint8Array([0x47,0x49,0x46])], 'tiny.gif', { type: 'image/gif' });
      if (typeof window.handleFileUpload === 'function') {
        window.handleFileUpload({ target: { files: [tiny] }, preventDefault: () => {} });
      } else {
        const fileInput = document.getElementById('fileUploader');
        if (fileInput && fileInput.onchange) {
          Object.defineProperty(fileInput, 'files', { value: [tiny] });
          fileInput.onchange({ target: { files: [tiny] }, preventDefault: () => {} });
        }
      }
    } catch (e) {
      console.warn('probe upload endpoint failed', e);
    } finally {
      window.fetch = origFetch;
    }

    if (found) {
      localStorage.setItem(ENDPOINT_KEY, found);
      return found;
    }

    const base = (typeof window.KANO_baseURL === 'string') ? window.KANO_baseURL : '';
    const candidates = [ base + '/api/upload', base + '/api/upload_image', base + '/api/uploads' ];
    return candidates[0];
  }

  async function uploadViaEndpoint(endpoint, file) {
    const form = new FormData();
    form.append('file', file, file.name || 'video.mp4');
    const headers = (typeof window.common_headers === 'object' && window.common_headers) ? window.common_headers : {};
    const res = await fetch(endpoint, { method: 'POST', headers, body: form });
    const ct = (res.headers.get('content-type') || '').toLowerCase();
    if (ct.includes('application/json')) return await res.json();
    const text = await res.text();
    try { return JSON.parse(text); } catch { return { url: text }; }
  }

  function promptForUrl() {
    const cfg = readCfg();
    const url = window.prompt('请输入视频URL（例如：http://192.168.0.40:8000/wallpaper.mp4）', cfg.url || '');
    if (url === null) return;
    const v = String(url).trim();
    const c = readCfg();
    c.url = v;
    c.enabled = true;
    saveCfg(c);
    applyVideoCfg(ensureVideoLayer(), c);
    toast('已保存并启用背景视频', 'green');
    try { refreshTopToggleBtn && refreshTopToggleBtn(); } catch {}
  }

  function openModal() {
    if (document.getElementById('BG_VIDEO_MODAL')) return;
    const overlay = document.createElement('div');
    overlay.id = 'BG_VIDEO_MODAL';
    overlay.className = 'mask';
    overlay.style.position = 'fixed';
    overlay.style.left = '0';
    overlay.style.top = '0';
    overlay.style.right = '0';
    overlay.style.bottom = '0';
    overlay.style.background = 'rgba(0,0,0,0.4)';
    overlay.style.backdropFilter = 'blur(4px)';
    overlay.style.webkitBackdropFilter = 'blur(4px)';
    overlay.style.zIndex = '9999';

    const panel = document.createElement('div');
    panel.style.position = 'absolute';
    panel.style.left = '50%';
    panel.style.top = '50%';
    panel.style.transform = 'translate(-50%, -50%)';
    panel.style.width = '90%';
    panel.style.maxWidth = '680px';
    panel.style.maxHeight = '78%';
    panel.style.background = 'rgba(255,255,255,0.06)';
    panel.style.color = '#e7ebf5';
    panel.style.border = '1px solid rgba(255,255,255,0.12)';
    panel.style.borderRadius = '10px';
    panel.style.boxShadow = '0 12px 30px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.04)';
    panel.style.backdropFilter = 'blur(16px)';
    panel.style.webkitBackdropFilter = 'blur(16px)';
    panel.style.padding = '14px';
    panel.style.display = 'flex';
    panel.style.flexDirection = 'column';

    const header = document.createElement('div');
    header.style.display = 'flex';
    header.style.alignItems = 'center';
    header.style.justifyContent = 'space-between';
    header.style.marginBottom = '8px';
    const title = document.createElement('strong');
    title.style.color = '#e7ebf5';
    title.textContent = '背景视频';
    const headerRight = document.createElement('div');
    const btnCloseX = document.createElement('button');
    btnCloseX.classList.add('btn');
    btnCloseX.textContent = '关闭';
    btnCloseX.onclick = () => { try { document.body.removeChild(overlay); } catch {} };
    headerRight.appendChild(btnCloseX);
    header.appendChild(title);
    header.appendChild(headerRight);

    const content = document.createElement('div');
    content.style.overflow = 'auto';
    content.style.flex = '1';
    content.style.border = '1px solid rgba(255,255,255,0.12)';
    content.style.borderRadius = '8px';
    content.style.padding = '12px';
    content.style.background = 'rgba(255,255,255,0.04)';

    const cfg = readCfg();

    const row1 = document.createElement('p');
    const labelEnable = document.createElement('label');
    const enable = document.createElement('input');
    enable.type = 'checkbox'; enable.checked = !!cfg.enabled; enable.style.marginRight = '6px';
    labelEnable.appendChild(enable);
    labelEnable.appendChild(document.createTextNode('启用背景视频？'));
    row1.appendChild(labelEnable);

    // 按钮式启用（仿指示灯）
    const btnEnable = document.createElement('button');
    btnEnable.classList.add('btn');
    btnEnable.style.marginLeft = '10px';
    const setBtnEnableStyle = (on) => {
      btnEnable.style.backgroundColor = on ? DARK_BG : LIGHT_BG;
      btnEnable.style.color = '#333';
      btnEnable.textContent = on ? '启用：开' : '启用：关';
      btnEnable.setAttribute('aria-pressed', on ? 'true' : 'false');
    };
    setBtnEnableStyle(!!cfg.enabled);
    btnEnable.onclick = () => {
      const c = readCfg();
      c.enabled = !c.enabled; saveCfg(c);
      enable.checked = c.enabled;
      setBtnEnableStyle(c.enabled);
      applyVideoCfg(ensureVideoLayer(), c);
      // 同步顶部按钮样式
      try { refreshTopToggleBtn && refreshTopToggleBtn(); } catch {}
    };
    row1.appendChild(btnEnable);

    const row2 = document.createElement('p');
    const span = document.createElement('span'); span.textContent = '视频网址：';
    const inputUrl = document.createElement('input'); inputUrl.placeholder = '输入视频URL'; inputUrl.value = cfg.url || '';
    inputUrl.style.width = '60%'; inputUrl.style.marginLeft = '6px';
    inputUrl.style.background = 'rgba(255,255,255,0.06)';
    inputUrl.style.border = '1px solid rgba(255,255,255,0.18)';
    inputUrl.style.color = '#e7ebf5';
    inputUrl.style.outline = 'none';
    inputUrl.style.padding = '6px 8px';
    inputUrl.style.borderRadius = '6px';
    const btnUpload = document.createElement('button'); btnUpload.classList.add('btn'); btnUpload.textContent = '上传视频(不限制大小)'; btnUpload.style.marginLeft = '8px';
    row2.appendChild(span); row2.appendChild(inputUrl); row2.appendChild(btnUpload);

    const row3 = document.createElement('div');
    row3.style.display = 'flex'; row3.style.flexWrap = 'wrap'; row3.style.gap = '8px'; row3.style.alignItems = 'center'; row3.style.margin = '6px 0';
    const mkCtl = (label, min, max, step, get, set) => {
      const wrap = document.createElement('label'); wrap.style.display = 'inline-flex'; wrap.style.alignItems = 'center'; wrap.style.gap = '6px';
      const s = document.createElement('span'); s.textContent = label;
      const inp = document.createElement('input'); inp.type = 'number'; inp.min = min; inp.max = max; inp.step = step; inp.style.width = '72px';
      inp.value = String(get()); inp.onchange = () => set(Number(inp.value));
      wrap.appendChild(s); wrap.appendChild(inp); return wrap;
    };
    row3.appendChild(mkCtl('音量', 0, 1, 0.1, () => readCfg().volume ?? 0, v => { const c = readCfg(); c.volume = Math.max(0, Math.min(1, v || 0)); saveCfg(c); applyVideoCfg(ensureVideoLayer(), c); }));
    row3.appendChild(mkCtl('速度', 0.25, 4, 0.25, () => readCfg().playbackRate ?? 1, v => { const c = readCfg(); c.playbackRate = Math.max(0.25, Math.min(4, v || 1)); saveCfg(c); applyVideoCfg(ensureVideoLayer(), c); }));
    row3.appendChild(mkCtl('透明度', 0, 1, 0.05, () => readCfg().opacity ?? 1, v => { const c = readCfg(); c.opacity = Math.max(0, Math.min(1, v || 1)); saveCfg(c); applyVideoCfg(ensureVideoLayer(), c); }));
    const btnMute = document.createElement('button'); btnMute.classList.add('btn');
    const refreshMute = () => { btnMute.textContent = (readCfg().muted ? '静音：开' : '静音：关'); };
    refreshMute(); btnMute.onclick = () => { const c = readCfg(); c.muted = !c.muted; saveCfg(c); applyVideoCfg(ensureVideoLayer(), c); refreshMute(); };
    row3.appendChild(btnMute);

    enable.onchange = () => { const c = readCfg(); c.enabled = enable.checked; saveCfg(c); applyVideoCfg(ensureVideoLayer(), c); };
    inputUrl.onchange = () => { const c = readCfg(); c.url = inputUrl.value.trim(); saveCfg(c); applyVideoCfg(ensureVideoLayer(), c); };
    btnUpload.onclick = async () => { try {
      const file = await pickFile('video/*'); if (!file) return; const endpoint = await discoverUploadEndpoint(); if (!endpoint) return toast('无法定位上传接口', 'red');
      toast('开始上传视频...', ''); const json = await uploadViaEndpoint(endpoint, file);
      const path = (json && (json.url || json.path || json.file || json.location || json.result)) ? (json.url || json.path || json.file || json.location || json.result) : '';
      if (!path) return toast('上传响应异常', 'red'); inputUrl.value = path; const c = readCfg(); c.url = path; saveCfg(c); applyVideoCfg(ensureVideoLayer(), c); toast('上传成功', 'green');
    } catch (e) { console.error(e); toast('上传失败：' + (e && e.message ? e.message : e), 'red'); } };

    content.appendChild(row1);
    content.appendChild(row2);
    content.appendChild(row3);

    const footer = document.createElement('div');
    footer.style.display = 'flex'; footer.style.justifyContent = 'flex-end'; footer.style.gap = '8px'; footer.style.marginTop = '10px';
    const btnSubmit = document.createElement('button'); btnSubmit.classList.add('btn'); btnSubmit.textContent = '提交';
    btnSubmit.onclick = () => { const c = readCfg(); saveCfg(c); applyVideoCfg(ensureVideoLayer(), c); toast('已保存', 'green'); };
    const btnClose = document.createElement('button'); btnClose.classList.add('btn'); btnClose.textContent = '关闭';
    btnClose.onclick = () => { try { document.body.removeChild(overlay); } catch {} };
    footer.appendChild(btnSubmit); footer.appendChild(btnClose);

    panel.appendChild(header);
    panel.appendChild(content);
    panel.appendChild(footer);
    overlay.appendChild(panel);
    document.body.appendChild(overlay);
  }

  function mountTopButton() {
    if (document.getElementById('bg_video_top_btn')) return;
    const bar = getActionsBar();
    if (!bar) return;
    const btn = document.createElement('button');
    btn.id = 'bg_video_top_btn';
    btn.classList.add('btn');
    btn.textContent = '背景视频';
    btn.onclick = () => { promptForUrl(); };

    const toggle = document.createElement('button');
    toggle.id = 'bg_video_toggle_btn';
    toggle.classList.add('btn');
    toggle.style.marginLeft = '8px';
    const setToggleStyle = (on) => {
      toggle.style.backgroundColor = on ? DARK_BG : LIGHT_BG;
      toggle.style.color = '#333';
      toggle.textContent = on ? '背景视频：开' : '背景视频：关';
      toggle.setAttribute('aria-pressed', on ? 'true' : 'false');
    };
    const refreshTopToggleBtn = () => {
      try {
        const c = readCfg();
        setToggleStyle(!!c.enabled);
      } catch {}
    };
    window.refreshTopToggleBtn = refreshTopToggleBtn;
    toggle.onclick = () => {
      const c = readCfg();
      c.enabled = !c.enabled; saveCfg(c);
      applyVideoCfg(ensureVideoLayer(), c);
      refreshTopToggleBtn();
    };

    bar.appendChild(btn);
    bar.appendChild(toggle);
    refreshTopToggleBtn();
  }

  function boot() {
    ensureVideoLayer();
    let tries = 0;
    const timer = setInterval(() => {
      tries++;
      try { mountTopButton(); } catch (e) { console.warn(e); }
      if (document.getElementById('bg_video_top_btn') || tries > 40) clearInterval(timer);
    }, 250);

    const onBgDblClick = (ev) => {
      const t = ev.target;
      const isBg = (t === document.body) || (t && t.id === 'BG');
      const isUi = t && (t.closest && t.closest('button, .btn, input, select, textarea, label, a, .collapse, #BG_VIDEO_MODAL'));
      if (isBg && !isUi) promptForUrl();
    };
    try { document.addEventListener('dblclick', onBgDblClick, true); } catch {}
  }

  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot);
  else boot();
})();
//</script>